//solution adapter
//$Id: solution.h 670 2011-02-27 11:52:14Z Oleg.Bulychov $
#pragma once

#include <list>
#include <algorithm>
#include "src/heo/include/sys_api.h"

template<class A, class B>
struct solution;


template<class TSolution>
struct Solution_Pool
{
    std::vector<TSolution> sol_list_;
    typedef typename std::vector<TSolution>::iterator       iterator;
    typedef typename std::vector<TSolution>::const_iterator const_iterator;

    void resize(size_t nSize)
    {
        sol_list_.resize(nSize);
    }

    template<class TSolver>
    bool init(TSolver& solver, int omp_np)
    {
        typename TSolver::TEnvironment* env = solver.get_Environment();
        if (env->initial_solution_.length() > 0)
        {//:read from file (example - onemax.h)
            return TSolution::read(env, env->initial_solution_, *this);
        }
        else
        {//:generate by omp_np
            random_generator& rnd = solver.get_Rnd();
            sol_list_.resize(omp_np, TSolution());
            iterator it = sol_list_.begin();
            for (; it != sol_list_.end(); ++it)
            {
                it->init(env, rnd);
                it->generate(env, rnd);
                it->evaluate(env, rnd);
            }
        }
        return true;
    }

    template<class E>
    void output(E* env)
    {
        size_t i = 0;
        size_t count = sol_list_.size();
        if (count > env->output_size_)
            count = env->output_size_;
        for (iterator it = sol_list_.begin(); it != sol_list_.end(); ++it, ++i)
        {
            if (i >= count)
                break;

            if (1 == count)
                std::cout << lf
                          << "solution:" << lf;
            else
                std::cout << lf
                          << "solution[" << i << "]:" << lf;

            it->print(std::cout, env);
        }
        std::cout << lf;
        if (env->output_dir_.length())
        {
            std::string name = env->output_dir_;
            sys_api::Create_Dir_Recursive(env->output_dir_.c_str());
            sys_api::Path_Append(name, "solution.dat");
            size_t id = 0;
            for (iterator it = sol_list_.begin(); it != sol_list_.end(); ++it, ++id)
            {
                it->write(env, name, id, count);
            }
        }
    }

    void sort()
    {
        std::sort(sol_list_.begin(), sol_list_.end(), Better_Solution);
    }
private:
    static bool Better_Solution(TSolution const& left, TSolution const& right)
    {
        typename TSolution::TCostType fa = left.get_Cost();
        typename TSolution::TCostType fb = right.get_Cost();
        return typename TSolution::TDirection()(fa, fb);
    }
};

//EOF!
